package com.xqboss.apps.service.market;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xqboss.apps.domain.market.MarketMain;
import com.xqboss.apps.domain.nft.Category;
import com.xqboss.apps.domain.nft.Nft;
import com.xqboss.apps.enums.market.MarketTypeEnum;
import com.xqboss.apps.enums.nft.NftTypeEnum;
import com.xqboss.apps.dto.market.MarketDto;
import com.xqboss.apps.mapper.market.MarketMainMapper;
import com.xqboss.apps.vo.market.MarketListVo;
import com.xqboss.apps.service.nft.CategoryService;
import com.xqboss.common.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import static com.xqboss.common.utils.AsyncHandlerUtil.run;


/**
 * 市场主表接口
 *
 * @author wangcong
 * @date 2023-11-27
 */
@Service
public class MarketMainService extends ServiceImpl<MarketMainMapper, MarketMain> {


    /**
     * 获取市场一级列表
     * @param dto
     * @return
     */
    public List<MarketListVo> getMarketList(MarketDto dto) {
        List<MarketListVo> marketList = baseMapper.getMarketList(dto);
        if (CollUtil.isNotEmpty(marketList)) {
            ArrayList<CompletableFuture<Void>> futures = new ArrayList<>(marketList.size()*3);
            for (MarketListVo market : marketList) {
                //市场在卖专卖中最低价
                CompletableFuture<Void> a = run(()->market.getMarketVo().setLowestPrice(baseMapper.selectMarketByNftIdMin(market.getNftId(), market.getType().getValue(), market.getIsNew())));
                CompletableFuture<Void> b;
                if (market.getIsVirtual()) {
                    b = run(()->market.getMarketVo().setMaxPrice(market.getDisplayMaxPrice()));
                } else {
                    //市场已卖最高价
                    b = run(()->market.getMarketVo().setMaxPrice(baseMapper.selectMarketByNftIdMax(market.getNftId(), market.getType().getValue(), market.getIsNew())));
                }
                //市场在售数量
                CompletableFuture<Void> c = run(()->market.getMarketVo().setSellCount(baseMapper.selectMarketByNftIdSell(market.getNftId(), market.getType().getValue(), market.getIsNew())));

                futures.addAll(CollUtil.toList(a,b,c));
            }
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        }
        return  marketList;
    }

    public IPage<MarketListVo> getMarketListPlus(MarketDto<MarketListVo> dto) {
        IPage<MarketListVo> iPage = baseMapper.getMarketListPlus(dto.newPage(),dto);
        if (ObjUtil.isNotEmpty(iPage) && CollUtil.isNotEmpty(iPage.getRecords())) {
            ArrayList<CompletableFuture<Void>> futures = new ArrayList<>(iPage.getRecords().size()*3);
            for (MarketListVo market : iPage.getRecords()) {
                //市场在卖专卖中最低价
                CompletableFuture<Void> a = run(()->market.getMarketVo().setLowestPrice(baseMapper.selectMarketByNftIdMin(market.getNftId(), market.getType().getValue(), market.getIsNew())));
                CompletableFuture<Void> b;
                if (market.getIsVirtual()) {
                    b = run(()->market.getMarketVo().setMaxPrice(market.getDisplayMaxPrice()));
                } else {
                    //市场已卖最高价
                    b = run(()->market.getMarketVo().setMaxPrice(baseMapper.selectMarketByNftIdMax(market.getNftId(), market.getType().getValue(), market.getIsNew())));
                }
                //市场在售数量
                CompletableFuture<Void> c = run(()->market.getMarketVo().setSellCount(baseMapper.selectMarketByNftIdSell(market.getNftId(), market.getType().getValue(), market.getIsNew())));

                futures.addAll(CollUtil.toList(a,b,c));
            }
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        }
        return  iPage;
    }


    @Autowired
    private CategoryService categoryService;

    /**
     * 市场创建nft
     *
     * @param nft
     * @return
     */
    public boolean addMarket(Nft nft) {
        List<MarketMain> mainList = list(new LambdaQueryWrapper<MarketMain>()
                .eq(MarketMain::getSourceId, nft.getId()));
        if (CollUtil.isEmpty(mainList)) {
            Category category = categoryService.getById(nft.getCategoryId());

            MarketMain main = new MarketMain();
            main.setId(IdUtil.getSnowflakeNextId());
            if (nft.getNftType() == NftTypeEnum.NORMAL) {
                main.setType(MarketTypeEnum.NORMAL);
            } else if (nft.getNftType() == NftTypeEnum.EQUIPMENT) {
                main.setType(MarketTypeEnum.EQUIPMENT);
            }
            main.setSourceId(nft.getId());
            main.setTitle(nft.getTitle() + "(全新)");
            main.setImg(nft.getMainImg());
            if (category != null) {
                main.setCategoryName(category.getName());
            }
            if (category != null && category.getParentId() != null) {
                Category pcCategory = categoryService.getById(category.getParentId());
                main.setPcName(pcCategory == null ? null : pcCategory.getName());
            }
            //全新
            main.setIsNew(true);
            if (nft.getNftType().equals(NftTypeEnum.EQUIPMENT)) {
                save(main);
            }

            //非全新
            main.setId(IdUtil.getSnowflakeNextId());
            if (nft.getNftType().equals(NftTypeEnum.EQUIPMENT)) {
                main.setTitle(nft.getTitle() + "(使用过)");
            }else{
                main.setTitle(nft.getTitle());
            }
            main.setIsNew(false);
            save(main);

        }

        boolean b = update(new LambdaUpdateWrapper<MarketMain>()
                .set(MarketMain::getDelFlag, nft.getIsResell().getValue() == 0)
                .eq(MarketMain::getSourceId, nft.getId()));
        if (!b) {
            throw new ServiceException("关闭市场转卖失败");
        }
        return true;
    }
}
